import { useState, useRef, useEffect, createContext } from 'react'

import io from 'socket.io-client';

const ConnContext = createContext({
  cred: [],

  cast: () => {},
  send: () => {},
  release: () => {},

  post: () => {},
  saveCred: () => {},
  goto: () => {},
})

const ConnProvider = ({url, children}) => {

  const sock = useRef();

  const [cred, setCred] = useState();

  const send = (code, msg) => {
    sock.current.emit(code, msg);
  }

  const cast = (event, handler) => {

    if (Object.keys(sock.current._callbacks).includes(`$${event}`)) {
      return;
    }

    const func = (data) => {
      handler(data, sock.current);
    }

    sock.current.on(event, func);

    return func;
  }

  const saveCred = (newCred) => {
    setCred(newCred);
  }

  const release = (event, func) => {
    sock.current.off(event, func);
  }

  useEffect(() => {

    if (sock.current === undefined) {
      sock.current = io(url)
      .on('connect', () => {
        console.log(`Connected as [${sock.current.id}]`);
      });
    }

    return () => {
      console.log('unmount');
      sock.current.close();
    };
  }, [])


  useEffect(() => {
 
    if (!cred) {
      console.log('update cred');
      const {role, sess} = sessionStorage;
      setCred({role, sess});
      // Object.assign(sessionStorage, {role:undefined, sess:undefined});
    }

    window.onbeforeunload = () => {
      console.log('before unload', cred);
      if (cred !== undefined) {
        Object.assign(sessionStorage, cred, {sess: Math.random().toString().slice(2)});
      }
    }
    
    return () => {
      window.onbeforeunload = null;
    };
	}, [cred]);

  const value = {
    cred,
    cast,
    send,
    release,
    saveCred,
  }

  return <ConnContext.Provider value={value}>
    {children}
  </ConnContext.Provider>
}

export {ConnContext, ConnProvider};